package cn.lg.soar.database.base.service.impl;

import cn.lg.soar.common.util.data.DataUtil;
import cn.lg.soar.database.base.entity.IBaseEntity;
import cn.lg.soar.database.base.service.IBaseService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public abstract class BaseServiceImpl<M extends BaseMapper<T>, T extends IBaseEntity> extends ServiceImpl<M, T> implements IBaseService<T> {

    private String idField;
    private String idName;
    @Autowired
    protected CacheManager cacheManager;

    protected String getIdField() {
        if (this.idField == null) {
            TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
            this.idField = tableInfo.getKeyColumn();
        }
        return this.idField;
    }

    protected String getIdName() {
        if (this.idName == null) {
            TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
            this.idName = tableInfo.getKeyProperty();
        }
        return this.idName;
    }

    @Override
    public Class<T> getEntityClass() {
        return this.entityClass;
    }

    @Override
    public List<T> listByIds(Collection<? extends Serializable> idList, String cacheName, CacheManager cacheManager) {
        if (DataUtil.isEmpty(idList)) {
            return Collections.emptyList();
        }
        Cache cache = cacheManager.getCache(cacheName);
        List<T> res = new ArrayList<>(idList.size());
        List<Serializable> ids = new ArrayList<>(idList.size());
        for (Serializable id : idList) {
            if (id == null) {
                continue;
            }
            T t = cache.get(id, entityClass);
            if (t == null) {
                ids.add(id);
            } else {
                res.add(t);
            }
        }
        if (DataUtil.isValuable(ids)) {
            List<T> list = super.listByIds(ids);
            for (T t : list) {
                res.add(t);
                cache.put(t.primaryKey(), t);
            }
        }
        return res;
    }

    @Override
    public List<T> listByIds(Collection<? extends Serializable> idList, String cacheName) {
        return listByIds(idList, cacheName, cacheManager);
    }

    @Override
    public boolean exist(QueryWrapper<T> wrapper) {
        wrapper.select("1");
        IPage<T> page = new Page<>(0, 1, false);
        return this.page(page, wrapper).getRecords().size() == 1;
    }

    @Override
    public boolean exist(LambdaQueryWrapper<T> wrapper) {
        IPage<T> page = new Page<>(0, 1, false);
        return this.page(page, wrapper).getRecords().size() == 1;
    }

    /**
     * 失效缓存
     * @param name 缓存名称
     * @param keys key列表
     */
    protected void evictCache(String name, Object...keys) {
        Cache cache = cacheManager.getCache(name);
        Assert.notNull(cache, "缓存不存在");
        // 逐条清理缓存
        for (Object key : keys) {
            cache.evict(key);
        }
    }

    /**
     * 失效缓存
     * @param name 缓存名称
     * @param keys key列表
     */
    protected void evictCache(String name, Collection<?> keys) {
        evictCache(name, DataUtil.collectionToArray(keys));
    }

    /**
     * 清空缓存
     * @param name
     */
    protected void clearCache(String name) {
        Cache cache = cacheManager.getCache(name);
        Assert.notNull(cache, "缓存不存在");
        cache.clear();
    }
}
